﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ini;
using System.Xml;
using System.Xml.XPath;
using System.IO;
using Microsoft.VisualBasic;
using System.Data;
using System.Data.Common;
using AlisV6Soap;
using AlisV6MQ;
using System.Diagnostics;


namespace CSequence
{
    public class CFileParameter
    {
        public string sName;
        public string sValue;
        public string sCalValue = "";
        public float fX;
        public float fY;
        public CStep m_Parent;
        public int iControlIndex;
        public string sID;
        public CFileParameter(){}
        
        public string ToXml()
        {
            string sRet;
            sRet = "<Name>" + sName  + "</Name>";
            sRet += "<Value>" + sValue + "</Value>";
            return sRet;
        }

        public CFileParameter(string sInName, string sInValue, string sInID)
        {
            sName = sInName;
            sValue = sInValue;
            sID = sInID;
        }

        public CFileParameter(string sSection)
        {
            string[] arrSec = sSection.Split('=');
            if (arrSec.Length == 1)
            {
                sName = arrSec[0];
                sValue = "";
            }
            else 
            {
                
                sName = arrSec[0];
                sValue = "";
                for (int i = 1; i < arrSec.Length; i++)
                {
                    if (i == (arrSec.Length-1)) 
                        sValue += arrSec[i];
                    else
                        sValue += arrSec[i] + "=";
                }

            }
        }
    }

    public class CInput : CFileParameter
    {
        public CInput(CStep oParent)
            : base()
        {
            m_Parent = oParent;
            int iMaxId = 5;
            foreach (CInput oIn in oParent.lInputs)
            {
                if (Convert.ToInt32(oIn.sID) > iMaxId)
                    iMaxId = Convert.ToInt32(oIn.sID);
            }
            sID = (iMaxId + 1).ToString();
        }

        public CInput(string sSection, CStep oParent)
            : base(sSection)
        {
            m_Parent = oParent;
            int iMaxId = 5;
            foreach (CInput oIn in oParent.lInputs)
            {
                if (Convert.ToInt32(oIn.sID) > iMaxId)
                    iMaxId = Convert.ToInt32(oIn.sID);
            }
            sID = (iMaxId + 1).ToString();
        }

        public CInput(string sInName,string sInPar,  string sInID,CStep oParent)
            : base(sInName, sInPar, sInID)
        {
            m_Parent = oParent;            
        }

        public string ToSql()
        {
            string sRet;
            sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAMS_VALUE ) ";
            sRet += "values (" + m_Parent.sProcessId + "," + m_Parent.sId + "," + sID + ",'I','" + sName + "','" + sValue + "');\r\n";
            return sRet;
        }

        public string ToCopySql()
        {
            string sRet;
            sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAMS_VALUE ) ";
            sRet += "values ($ProcessId$,$StepId$," + sID + ",'I','" + sName + "','" + sValue + "');\r\n";
            return sRet;
        }

    }

    public class COutput : CFileParameter
    {
        public COutput()
            : base()
        {
        }

       public COutput(string sSection, CStep oParent)
            : base(sSection)
        {
            m_Parent = oParent;
        }

       public COutput(string sName, string sVal, string sInID, CStep oParent)
           : base(sName, sVal, sInID)
       {
           m_Parent = oParent;
       }

       public string ToSql()
       {
           string sRet;
           sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAMS_VALUE ) ";
           sRet += "values (" + m_Parent.sProcessId + "," + m_Parent.sId + "," + sID + ",'O','" + sName + "','" + sValue + "');\r\n";
           return sRet;
       }

       public string ToCopySql()
       {
           string sRet;
           sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAMS_VALUE ) ";
           sRet += "values ($ProcessId$,$StepId$ ," + sID + ",'O','" + sName + "','" + sValue + "');\r\n";
           return sRet;
       }
    }

    public class CParam : CFileParameter
    {
        public CParam()
            : base()
        {
        }

        public CParam(string sSection, CStep oParent)
            : base(sSection)
        {
            m_Parent = oParent;
        }

        public CParam(string sName, string sVal, string sInID, CStep oParent)
            : base(sName, sVal, sInID)
        {
            m_Parent = oParent;
        }
    }

    public class CDisplay : CFileParameter
    {

        public void Save()
        {
            //m_Parent.oIniFile.IniWriteValue("Display", sName, sValue);
        }

        public CDisplay(CStep oParent) : base()
        {
            m_Parent = oParent;
        }

        public CDisplay(string sSection, CStep oParent): base(sSection)
        {
            m_Parent = oParent;
        }

        public CDisplay(string sName,string sVal, string sInID,CStep oParent) : base(sName, sVal, sInID)
        {
            m_Parent = oParent;
        }

        public string ToSql()
        {
            string sRet;
            sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAMS_VALUE ) ";
            sRet += "values (" + m_Parent.sProcessId + "," + m_Parent.sId + "," + sID + ",'D','" + sName + "','" + sValue + "');\r\n";
            return sRet;
        }
        public string ToCopySql()
        {
            string sRet;
            sRet = "insert into  T_API_QD_PROCESS_STEP_PARAMS (PROCESS_ID,STEP_ID,ID,PARAMS_TYPE, NAME, PARAMS_VALUE ) ";
            sRet += "values ($ProcessId$,$StepId$," + sID + ",'D','" + sName + "','" + (Convert.ToInt64(sValue) + 10).ToString() + "');\r\n";
            return sRet;
        }
    }

    public class CStep
    {
        private DbConnection m_connection = null;
        public IniFile oIniFile = null;
        FileSequence m_FileSequence;
        public bool bCalculated = false;
        //public int iControlIndex = -1;
        public string sErrorCode = "";
        public string sErrorMessage = "";
        private string sIniFilePath = "C:\\Sapiens\\Sequence\\Sequence.ini";
        public string sInFilename = "";
        public string sOutFilename = "";
        public string sName = "";
        public string sDir = "";
        public string sQueryName = "";
        public string sType = "";
        public string sMode = "";
        public string sProcessId = "";
        public string sId = "";
        enum Serialise { XML, Ini, Database };
        Serialise eSerialise;
        public string sLastRunInXml = "";
        public string sLastRunOutXml = "";
        public DateTime dtStart;
        public DateTime dtEnd;
        private List<string> ForList = new List<string>();
        public bool m_bFirstTimeInFor = true;
        public int m_iLoopCount;

        public delegate void ChangedEventHandler(object sender, EventArgs e);
        public event ChangedEventHandler Calculated;


        // List of the input and ouput params
        public List<CInput> lInputs = new List<CInput>();
        public List<COutput> lOutputs = new List<COutput>();
        public List<CDisplay> lDisplay = new List<CDisplay>();

        public string GetControlName()
        {
            string sRet = "";

            if (this.sType == "TextComment")
                sRet = "txtComment" + sId;
            else
                sRet = "usStep" + sId;
            return sRet;
        }

        public CStep(string sInPath, FileSequence oFileSequence)
        {
            bCalculated = false;
            m_FileSequence = oFileSequence;
            string sFilePath = sInPath;

            sName = Path.GetFileName(sInPath);
            sDir = Path.GetDirectoryName(sInPath);

            XmlDocument oXmlDoc = new XmlDocument();
            oXmlDoc.Load(sInPath);
            XmlNode oNode = oXmlDoc.SelectSingleNode("/Root/Step/@Type");
            if (oNode != null)
                sType = oNode.Value;

            oNode = oXmlDoc.SelectSingleNode("/Root/Step/@Name");
            if (oNode != null)
                sName = oNode.Value;

            oNode = oXmlDoc.SelectSingleNode("/Root/Step/@Mode");
            if (oNode != null)
                sMode = oNode.Value;

            oNode = oXmlDoc.SelectSingleNode("/Root/Step/@QueryName");
            if (oNode != null)
                sQueryName = oNode.Value;

            XmlNodeList nodeList1 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Input");
            int i = 0;
            foreach (XmlNode xName in nodeList1)
            {
                string sInName = xName.Attributes["Name"].Value;
                string sInValue = xName.Attributes["Value"].Value;
                if (sInName != null)
                {
                    CInput oIn = new CInput(sInName, sInValue, i.ToString(), this);
                    i++;
                    lInputs.Add(oIn);
                }
            }

            XmlNodeList nodeList2 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Output");
            foreach (XmlNode xName in nodeList2)
            {
                COutput oOut = new COutput(xName.Attributes["Name"].Value, xName.Attributes["Value"].Value, i.ToString(), this);
                i++;
                lOutputs.Add(oOut);
            }

            /*XmlNodeList nodeList3 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Param");
            foreach (XmlNode xName in nodeList3)
            {
                CParam oPar = new CParam(xName.Attributes["Name"].Value, xName.Attributes["Value"].Value, i.ToString(), this);
                i++;
                lParams.Add(oPar);
            }*/

            XmlNodeList nodeList4 = oXmlDoc.SelectSingleNode("/Root/Step").SelectNodes("Display");
            foreach (XmlNode xName in nodeList4)
            {
                CDisplay oDis = new CDisplay(xName.Attributes["Name"].Value, xName.Attributes["Value"].Value, i.ToString(), this);
                i++;
                lDisplay.Add(oDis);
            }
        }

        public CStep(FileSequence oFileSequence, DbConnection oConnection)
        {
            m_FileSequence = oFileSequence;
            eSerialise = Serialise.Database;
            m_connection = oConnection;
            oIniFile = new IniFile(sIniFilePath);
            bCalculated = false;
        }

        public CStep()
        {
            oIniFile = new IniFile(sIniFilePath);
            bCalculated = false;
        }

        public CStep(DbDataReader oDataReader, DbConnection oConnection, FileSequence oFileSequence)
        {
            try
            {
                eSerialise = Serialise.Database;
                m_FileSequence = oFileSequence;
                m_connection = oConnection;
                sProcessId = oDataReader["PROCESS_ID"].ToString();
                sType = IdToType(oDataReader["STYPE"].ToString());
                sName = oDataReader["NAME"].ToString();
                sQueryName = oDataReader["QUERY_NAME"].ToString();
                sId = oDataReader["ID"].ToString();
                sMode = oDataReader["STEP_MODE"].ToString();
                oIniFile = new IniFile(sIniFilePath);
                bCalculated = false;
            }
            catch
            {

            }
        }

        public void Save()
        {
            if (eSerialise == Serialise.XML)
            {
                if (File.Exists(sDir + "\\" + sName + ".bak"))
                    File.Delete(sDir + "\\" + sName + ".bak");

                if (File.Exists(sDir + "\\" + sName + ".xml"))
                    File.Copy(sDir + "\\" + sName + ".xml", sDir + "\\" + sName + ".bak");

                StreamWriter writer = new StreamWriter(sDir + "\\" + sName + ".xml");
                writer.Write(ToXml());
                writer.Close();
            }
            else if (eSerialise == Serialise.Database)
            {
                string sSql = CSqlString.GetDeleteProcess(CSqlString.GetConnectionType(m_connection.ConnectionString), sProcessId, sId, ToSql());
                RunSql(sSql);
            }
        }

        private void RunSql(String sSql)
        {
            try
            {
                DbCommand command = m_connection.CreateCommand();
                command.CommandText = sSql;
                command.CommandType = CommandType.Text;

                int iRows = command.ExecuteNonQuery();
                command.Dispose();
            }
            catch (Exception ex)
            {
                sErrorMessage += ex.Message + " (" + sSql + ")";
            }
        }

        public string ToSql()
        {
            string sSql = "insert into T_API_QD_PROCESS_STEP (PROCESS_ID,ID,NAME,TYPE,QUERY_NAME,STEP_MODE ) ";
            sSql += "values (" + sProcessId + "," + sId  + ",";
            sSql += "'" + sName.Replace("'","''") + "'," + GetTypeNumber(sType) + " ,'" + sQueryName + "', '" + sMode + "');\r\n";
            
            foreach (CInput Input in lInputs)
                sSql += Input.ToSql();

            foreach (COutput Output in lOutputs)
                sSql += Output.ToSql();

            foreach (CDisplay Display in lDisplay)
                sSql += Display.ToSql();

            return sSql;
        }

        public string ToCopySql()
        {
            string sSql = "insert into T_API_QD_PROCESS_STEP (PROCESS_ID,ID,NAME,TYPE,QUERY_NAME,STEP_MODE ) ";
            sSql += "values ($ProcessId$,$StepId$,";
            sSql += "'" + sName.Replace("'", "''") + "-Copy'," + GetTypeNumber(sType) + " ,'" + sQueryName + "', '" + sMode + "');\r\n";

            foreach (CInput Input in lInputs)
                sSql += Input.ToCopySql();

            foreach (COutput Output in lOutputs)
                sSql += Output.ToCopySql();

            foreach (CDisplay Display in lDisplay)
                sSql += Display.ToCopySql();

            return sSql;
        }
        
        public string GetTypeNumber(string sType)
        {
            string sRet="";
            switch (sType)
            {
                case "Constants":
                    sRet = "0";
                    break;
                case "QueryDef":
                    sRet = "1";
                    break;
                case "QueryDefUpdate":
                    sRet = "2";
                    break;
                case "UpdateQueryDef":
                    sRet = "2";
                    break;
                case "UpdateAlisWebService":
                    sRet = "3";
                    break;
                case "AlisWebService":
                    sRet = "4";
                    break;
                case "IF":
                    sRet = "5";
                    break;
                case "ELSE":
                    sRet = "6";
                    break;
                case "END IF":
                    sRet = "7";
                    break;
                case "FOR":
                    sRet = "8";
                    break;
                case "END FOR":
                    sRet = "9";
                    break;
                case "QueryDefProcess":
                    sRet = "10";
                    break;
                case "FOR LIST":
                    sRet = "11";
                    break;
                case "END FOR LIST":
                    sRet = "12";
                    break;
                case "Calculation":
                    sRet = "13";
                    break;
                case "ChildUpdateQueryDef":
                    sRet = "14";
                    break;
                case "TextComment":
                    sRet = "15";
                    break;
                case "Input":
                    sRet = "16";
                    break;
                case "Output":
                    sRet = "17";
                    break;
                case "Map":
                    sRet = "18";
                    break;

                default:
                    Debug.Assert(false);
                    break;

            }
            return sRet;
        }

        public string ToXml() 
        {
            string sRet = "";
            sRet = "<Root>\r\n";
            sRet += " <Step Name=\"" + sName + "\" Mode=\"" + sMode + "\" Type=\"" + sType + "\" QueryName=\"" + sQueryName + "\">\r\n";
            
            sRet += "  ";
            foreach (CInput oIn in lInputs)
                sRet += "   <Input Name=\"" + oIn.sName + "\" Value=\"" + oIn.sValue+ "\"></Input>\r\n";
            
            foreach (COutput oOut in lOutputs)
                sRet += "   <Output Name=\"" + oOut.sName + "\" Value=\"" + oOut.sValue + "\"></Output>\r\n";

            //foreach (CParam oPar in lParams)
            //    sRet += "   <Param Name=\"" + oPar.sName + "\" Value=\"" + oPar.sValue + "\"></Param>\r\n";

            foreach (CDisplay oDis in lDisplay)
                sRet += "   <Display Name=\"" + oDis.sName + "\" Value=\"" + oDis.sValue + "\"></Display>\r\n";
         

            sRet += " </Step>\r\n";
            sRet += "</Root>\r\n";
            return sRet;
        }

        public string GetInputValue(string sInName)
        {
            string sRet = "";
            CInput oIn = lInputs.Find(element => element.sName == sInName);
            if (oIn != null)
                sRet = oIn.sValue;

            return sRet;
        }

        public void SetInputValue(string sInName, string sValue)
        {
            CInput oIn = lInputs.Find(element => element.sName == sInName);
            if (oIn != null)
                oIn.sValue = sValue;
            else
            {
                CInput oNewIn = new CInput(this);
                oNewIn.sName = sInName;
                oNewIn.sValue = sValue;
                lInputs.Add(oNewIn);
            }
        }

        public COutput FindOutput(string sName)
        {
            COutput oOut = lOutputs.Find(element => element.sName == sName);
            return oOut;
        }

        public CInput FindInput(string sName)
        {
            CInput oIn = lInputs.Find(element => element.sName == sName);
            return oIn;
        }

        public string GetInputCalValue(string sInName)
        {
            string sRet = "";
            CInput oIn = lInputs.Find(element => element.sName == sInName);
            if (oIn != null)
                sRet = oIn.sCalValue;

            return sRet;
        }

        public string GetOutputValue(string sOutName)
        {
            string sRet = "";
            COutput oOut = lOutputs.Find(element => element.sName == sOutName);
            if (oOut != null)
                sRet = oOut.sValue;

            return sRet;
        }

        public string GetDisplayValue(string sDisName)
        {
            string sRet = "";
            CDisplay oDis = lDisplay.Find(element => element.sName == sDisName);
            if (oDis != null)
                sRet = oDis.sValue;

            return sRet;
        }

        public string GetDisplayValue(string sDisName, string sDefault)
        {
            string sRet = sDefault;
            CDisplay oDis = lDisplay.Find(element => element.sName == sDisName);
            if (oDis != null)
                sRet = oDis.sValue;
            if (sRet == "")
                sRet = sDefault;
            return sRet;
        }

        public void SetDisplayValue(string sDisName, string sValue)
        {
            
            CDisplay oDis = lDisplay.Find(element => element.sName == sDisName);
            if (oDis == null)
            {
                string sCount = (lDisplay.Count()+1).ToString();
                CDisplay oDisNew = new CDisplay(sDisName, sValue, sCount, this);
                lDisplay.Add(oDisNew);
                m_FileSequence.bIsDirty = true;
            }
            else                                  
            {
                if (oDis.sValue != sValue)
                {
                    oDis.sValue = sValue;
                    m_FileSequence.bIsDirty = true;
                }
            }
        }

        private string IdToType(string sId)
        {
            string sType = "-";
            switch (sId)
            {
                case "0":
                    sType = "Constants";
                    break;
                case "1":
                    sType = "QueryDef";
                    break;
                case "2":
                    sType = "QueryDefUpdate";
                    break;
                case "3":
                    sType = "UpdateAlisWebService";
                    break;
                case "4":
                    sType = "AlisWebService";
                    break;
                case "5":
                    sType = "IF";
                    break;
                case "6":
                    sType = "ELSE";
                    break;
                case "7":
                    sType = "END IF";
                    break;
                case "8":
                    sType = "FOR";
                    break;
                case "9":
                    sType = "END FOR";
                    break;
                case "10":
                    sType = "QueryDefProcess";
                    break;
                case "11":
                    sType = "FOR LIST";
                    break;
                case "12":
                    sType = "END FOR LIST";
                    break;
                case "13":
                    sType = "Calculation";
                    break;
                case "14":
                    sType = "ChildUpdateQueryDef";
                    break;
                case "15":
                    sType = "TextComment";
                    break;
                case "16":
                    sType = "Input";
                    break;
                case "17":
                    sType = "Output";
                    break;
                case "18":
                    sType = "Map";
                    break;

                default:
                    Debug.Assert(false);
                    break;
                }
            return sType;
        }

        public override string ToString()
        {
            string sRet = " " + sName + "," + sType + "\r\n";

            foreach (CInput oIn in lInputs)
                sRet += " >" + oIn.sName + "," + oIn.sValue + "," + oIn.sCalValue + "\r\n";

            foreach (COutput oOut in lOutputs)
                sRet += " <" + oOut.sName + "," + oOut.sCalValue + "\r\n";

            foreach (CDisplay oDis in lDisplay)
                sRet += " @" + oDis.sName + "," + oDis.sValue + "\r\n";

            return sRet;
        }

        public void CalculateIf()
        {
            // An If step must have 3 inputs ( A == B)
            // A and B and inputs, the == is the operator
            string sOperator="", sA="", sB="";
            if (lInputs.Count < 2)
            {
                sErrorCode="2";
                sErrorMessage = "'If' step must have 2 or 3 Inputs";
            }
            else
            {
                sA = lInputs[0].sCalValue;
                sOperator = lInputs[1].sValue;
                // B os optional depending upon the sOperator
                if (lInputs.Count >= 3)
                    sB = lInputs[2].sCalValue;
         
                switch (sOperator.ToLower())
                {
                    case "==":
                    case "=":
                        if (sA == sB) 
                            m_FileSequence.bIfElseFlag = false;
                        else
                            m_FileSequence.bIfElseFlag = true;

                        if (lOutputs.Count() > 0)
                            lOutputs[0].sCalValue = (sA == sB).ToString();

                        break;

                    case "!=":
                    case "<>":
                        if (sA != sB) 
                            m_FileSequence.bIfElseFlag = false;
                        else
                            m_FileSequence.bIfElseFlag = true;
                        
                        if (lOutputs.Count() > 0)
                            lOutputs[0].sCalValue = (sA != sB).ToString();

                           break;

                    case "isnull":
                           if (sA == null)
                               sA = "";
                        if (sA != "") 
                            m_FileSequence.bIfElseFlag = true;
                        else
                            m_FileSequence.bIfElseFlag = false;
                        
                         if (lOutputs.Count() > 0)
                            lOutputs[0].sCalValue = (sA == "").ToString();
                        break;

                    }
                bCalculated = true;                
            }
        }

        public bool  CalculateQueryDef(bool bIsWebService, string sInFilename, string sOutFilename)
        {
            bool bFinish = false;
            string sRet="";
            string sSend = CreateInputQueryDef();

            CAlisV6MQ oCAlisV6MQ =null;
            CAlisV6Soap oCAlisV6Soap =null;

            if (bIsWebService)
            {
                string sUrl = oIniFile.IniReadValue("WebServices", "URL");                
                oCAlisV6Soap = new CAlisV6Soap(sUrl);
                sRet = oCAlisV6Soap.SendAndGetMessage(sSend);
            }
            else
            {
                oCAlisV6MQ = new CAlisV6MQ();
                string sQueueManager = oIniFile.IniReadValue("MQ", "QueueManager");
                string sChannel = oIniFile.IniReadValue("MQ", "Channel");
                string sServer = oIniFile.IniReadValue("MQ", "Server");
                string sRequestQueue = oIniFile.IniReadValue("MQ", "RequestQueue");
                string sResponseQueue = oIniFile.IniReadValue("MQ", "ResponseQueue");
                oCAlisV6MQ.Init(sServer, sQueueManager, sRequestQueue, sResponseQueue, sChannel);
                sRet = oCAlisV6MQ.SendAndGetMessage(sSend); 
                oCAlisV6MQ = new CAlisV6MQ();
            }

            SaveResults( sInFilename,sOutFilename, sSend, sRet);
            this.sOutFilename = sOutFilename; this.sInFilename = sInFilename;
            sLastRunInXml = sSend; sLastRunOutXml = sRet;

            XmlDocument oXmlDoc = new XmlDocument();
            if (sRet.Length > 0)
            {
                try
                {
                    oXmlDoc.LoadXml(sRet);
                    foreach (COutput oOut in lOutputs)
                    {
                        XmlNode oNode = oXmlDoc.SelectSingleNode(oOut.sValue);
                        if (oNode != null)
                            oOut.sCalValue = oNode.Value;
                    }
                }
                catch (Exception ex)
                {

                }
                bCalculated = true;
            }
            else
                bFinish = true;

            return bFinish;
        }

        private void SaveResults(string sFilename1,string sFilename2, string sSend, string sRet)
        {
            try
            {
                if (sFilename1 != "")
                    System.IO.File.WriteAllText(sFilename1, sSend.Replace("<?xml version=\"1.0\" encoding=\"UTF8\"?>", ""));

                if (sFilename2 != "")
                    System.IO.File.WriteAllText(sFilename2, sRet.Replace("<?xml version=\"1.0\" encoding=\"UTF8\"?>", ""));
            }
            catch (Exception Ex)
            {

            }
        }
        
        public bool CalculateAlisWebService(string sInFilename, string sOutFilename)
        {
            return CalculateQueryDef(oIniFile.IniReadValue("Settings", "Communication", "") == "WebServices",
                              sInFilename, sOutFilename);
        }

        public bool CalculateUpdateAlisWebService(string sInFilename, string sOutFilename)
        {
            return CalculateUpdateQueryDef(oIniFile.IniReadValue("Settings", "Communication", "") == "WebServices",
                                    sInFilename, sOutFilename);
        }

        public bool CalculateUpdateQueryDef(string sInFilename, string sOutFilename)
        {
            return CalculateUpdateQueryDef(oIniFile.IniReadValue("Settings", "Communication", "") == "WebServices",
                                    sInFilename, sOutFilename);
        }

        public bool CalculateQueryDef(string sInFilename, string sOutFilename)
        {
            return CalculateQueryDef(oIniFile.IniReadValue("Settings", "Communication", "") == "WebServices",
                              sInFilename, sOutFilename);
        }

        public bool CalculateUpdateQueryDef(bool bIsWebService, string sInFilename, string sOutFilename)
        {
            bool bFinish = false;
            CAlisV6MQ oCAlisV6MQ = null;
            CAlisV6Soap oCAlisV6Soap = null;
            string sRet = "";

            // Get all the Queue details
            string sSend = CreateInputUpdateQueryDef();   

            if (bIsWebService)
            {
                string sUrl = oIniFile.IniReadValue("WebServices", "URL");
                oCAlisV6Soap = new CAlisV6Soap(sUrl);
                sRet = oCAlisV6Soap.SendAndGetMessage(sSend);
            }
            else
            {
                oCAlisV6MQ = new CAlisV6MQ();
                // Get all the Queue details 
                string sQueueManager = oIniFile.IniReadValue("MQ", "QueueManager");
                string sChannel = oIniFile.IniReadValue("MQ", "Channel");
                string sServer = oIniFile.IniReadValue("MQ", "Server");
                string sRequestQueue = oIniFile.IniReadValue("MQ", "RequestQueue");
                string sResponseQueue = oIniFile.IniReadValue("MQ", "ResponseQueue");

                string sUserName = oIniFile.IniReadValue("QDHeader", "UserName");
                string sLanguageId = oIniFile.IniReadValue("QDHeader", "LanguageId");
                string sCompanyId = oIniFile.IniReadValue("QDHeader", "CompanyId");
                
                if ((sQueueManager.Length == 0) || (sChannel.Length == 0) || (sServer.Length == 0) || (sLanguageId.Length == 0) ||
                (sRequestQueue.Length == 0) || (sResponseQueue.Length == 0) || (sUserName.Length == 0) ||
                (sCompanyId.Length == 0) || (sMode.Length == 0))
                {
                    // Raise an error 
                    sErrorCode = "2";
                    sErrorMessage = "Missing Inputs";
                }
                else
                {
                    if (oCAlisV6MQ.Init(sServer, sQueueManager, sRequestQueue, sResponseQueue, sChannel))
                    {
                        sRet = oCAlisV6MQ.SendAndGetMessage(sSend);
                    }

                }  
            }
            sLastRunInXml = sSend; sLastRunOutXml = sRet;
            SaveResults(sInFilename,sOutFilename, sSend, sRet);
            this.sOutFilename = sOutFilename; this.sInFilename = sInFilename;
            sLastRunInXml = sSend; sLastRunOutXml = sRet;

            XmlDocument oXmlDoc = new XmlDocument();
            if (sRet.Length > 0)
            {

                try
                {
                    oXmlDoc.LoadXml(sRet);
                    sErrorCode = oXmlDoc.SelectSingleNode("/Root/ReturnCode/text()").Value;
                    sErrorMessage = "";
                    if (sErrorCode == "2")
                    {
                        sErrorMessage = oXmlDoc.SelectSingleNode("/Root/Reason/Message/text()").Value;
                    }
                   
                    foreach (COutput oOut in lOutputs)
                    {
                        // Need to set the calValue from the input 
                        if (oOut.sValue.Substring(0, 6).ToLower() == "input>")
                        {
                            string[] arrOut = oOut.sValue.Split('>');
                            if (arrOut.Count() == 2)
                            {
                                CInput oIn = lInputs.Find(element => element.sName == arrOut[1]);
                                if (oIn != null)
                                    oOut.sCalValue = oIn.sCalValue;
                            }
                        }
                        else
                        {
                            XmlNode oNode = oXmlDoc.SelectSingleNode(oOut.sValue);
                            if (oNode != null)
                                oOut.sCalValue = oNode.Value;
                        }
                    }                    
                }
                catch (Exception e) 
                {
                    sErrorCode = "2";
                    sErrorMessage = e.Message;
                   
                }
                bCalculated = true;                
            }
            else
                bFinish = true;

            return bFinish;
        }

        private bool StandardInput(string sName)
        {
            bool bRet = false;
            if (sName == "QueueManager") bRet = true;
            if (sName == "Channel") bRet = true;
            if (sName == "Server") bRet = true;
            if (sName == "RequestQueue") bRet = true;
            if (sName == "ResponseQueue") bRet = true;
            if (sName == "UserName") bRet = true;
            if (sName == "Token") bRet = true;
            if (sName == "Password") bRet = true;
            if (sName == "LanguageId") bRet = true;
            if (sName == "CompanyId") bRet = true;
            if (sName == "Mode") bRet = true;
            return bRet;
        }

        public string GetResults()
        {
            string sRet="";
            foreach ( COutput oOut in lOutputs)
                sRet += oOut.sName + " , " + oOut.sCalValue + "\r\n";
            return sRet;
        }

        public bool Calculate(string sInFilename, string sOutFilename)
        {
            string sDebug= "";
            return Calculate(sInFilename, sOutFilename, ref sDebug);
        }

        public bool Calculate(string sInFilename,string sOutFilename, ref string sDebug)
        {
            bool bFinish = false;
            dtStart = DateTime.Now;
            CStep oStartStep = null;
            
            // Chech to see it any inputs need to be set from previously Calculated Setps 
            foreach (CInput oIn in lInputs)
            {
                string[] aIn = oIn.sValue.Split('>');
                if (aIn.Length == 2)
                {
                    string sStep = aIn[0]; string sInput = aIn[1];
                    CStep oSt = m_FileSequence.oSteps.Find(element => element.sName == sStep);
                    if (oSt != null)
                    {
                        if (!oSt.bCalculated)
                        {
                            oSt.Calculate("", "");
                        }

                        COutput oOut = oSt.lOutputs.Find(element => element.sName == sInput);
                        if (oOut != null)
                            oIn.sCalValue = oOut.sCalValue;                        
                    }
                    else
                    {
                        m_FileSequence.sLastError += "Cant find (" + oIn.sValue + ") in (" + this.sName + "." + oIn.sName + ")\r\n";
                    }
                }
                else
                {
                    if (oIn.sValue.Length > 0)
                    {
                        if (oIn.sValue.Substring(0, 1) == "=")
                        {
                            oIn.sCalValue = CallFunction(oIn.sValue);
                        }
                        else
                        {
                            if (oIn.sValue != "?")
                                oIn.sCalValue = oIn.sValue;
                        }
                    }
                }
            }

            // Now check and output values that need to be set 
            foreach (COutput oOut in lOutputs)
            {
                // Need to set the calValue from the input 
                if (oOut.sValue.Length >= 6)
                {
                    if (oOut.sValue.Substring(0, 6).ToLower() == "input>")
                    {
                        string[] arrOut = oOut.sValue.Split('>');
                        if (arrOut.Count() == 2)
                        {
                            CInput oIn = lInputs.Find(element => element.sName == arrOut[1]);
                            if (oIn != null)
                                oOut.sCalValue = oIn.sCalValue;
                        }
                        else
                            oOut.sCalValue = "";
                    }
                }
                else
                    oOut.sCalValue = "";
            }

            // Now do the actual calculation
            switch (sType)
            {
                case "Input":
                case "Output":
                case "Constants":
                    bFinish = CalculateConstants();
                    break;
                case "Map":
                    bFinish = CalculateMap();
                    break;
                case "QueryDef":
                    if (InputsEmpty())
                        bFinish = true;
                    else
                        bFinish = CalculateQueryDef(sInFilename, sOutFilename);
                    break;

                case "AlisWebService":
                    if (InputsEmpty())
                        bFinish = true;
                    else
                        bFinish = CalculateAlisWebService(sInFilename, sOutFilename);
                    break;

                case "UpdateAlisWebService":
                    if (InputsEmpty())
                        bFinish = true;
                    else
                        bFinish = CalculateUpdateAlisWebService(sInFilename, sOutFilename);
                    break;

                case "QueryDefUpdate":
                    if (InputsEmpty())
                        bFinish = true;
                    else
                        bFinish = CalculateUpdateQueryDef(sInFilename, sOutFilename);
                    break;

                case "QueryDefProcess":
                    if (InputsEmpty())
                        bFinish = true;
                    else
                        bFinish = CalculateQueryDefProcess(sInFilename, sOutFilename, ref sDebug);
                    break;

                case "ChildUpdateQueryDef":
                    if (lOutputs.Count() > 0)
                    {
                        lOutputs[0].sCalValue = "<" + lOutputs[0].sValue + " Mode=\"" + sMode + "\" Name=\"" + sQueryName + "\" id=\"0\">\r\n";
                        foreach (CInput oIn in lInputs)
                        {
                            if (oIn.sValue == "Null")
                                lOutputs[0].sCalValue += "<" + oIn.sName + " xsi:nil=\"true\"/>\r\n";
                            else
                            {
                                lOutputs[0].sCalValue += "<" + oIn.sName + ">" + oIn.sCalValue + "</" + oIn.sName + ">\r\n";
                            }
                        }
                        lOutputs[0].sCalValue += "</" + lOutputs[0].sValue + ">";
                    }                        
                    break;

                case "IF":
                    CalculateIf();
                    break;
                case "ELSE":
                    m_FileSequence.bIfElseFlag = !m_FileSequence.bIfElseFlag;
                    break;
                case "END IF":
                    m_FileSequence.bIfElseFlag = false;
                    break;

                case "FOR":
                    // Save the start of the for loop - the first time in the loop counter \
                    // iForCount will be set to 0;
                    m_FileSequence.sForStart = sId;
                    if (  m_FileSequence.iForCount == 0)
                        m_FileSequence.iForCount = 1;
                    bCalculated = true;
                    break;

                case "END FOR":
                    // Save the start of the for 
                    m_FileSequence.iForCount++;

                    oStartStep = m_FileSequence.oSteps.Find(element => element.sId == m_FileSequence.sForStart);
                    if (oStartStep != null)
                    {
                        if (oStartStep.lInputs.Count() > 0)
                        {
                            if (m_FileSequence.iForCount <= Convert.ToInt16(oStartStep.lInputs[0].sValue))
                                m_FileSequence.iCurrentStep = Convert.ToInt16(m_FileSequence.sForStart);
                            else
                                m_FileSequence.iForCount = 0;
                        }
                    }
                    bCalculated = true;
                    break;

                case "FOR LIST":
                    CalculateForList();
                    break;

                case "END FOR LIST":
                    oStartStep = m_FileSequence.oSteps.Find(element => element.sId == m_FileSequence.sForStart);
                    if (oStartStep != null)
                    {
                        if (oStartStep.m_iLoopCount < oStartStep.ForList.Count)
                            m_FileSequence.iCurrentStep = Convert.ToInt16(m_FileSequence.sForStart) -1;
                        bCalculated = true;
                    }
                    break;


                case "Calculation":
                    DoCalculate();
                    break;

            }
            bCalculated = true;
            dtEnd = DateTime.Now;
            return bFinish;
        }

        

        private bool CalculateMap()
        {
            if ((lInputs.Count() > 1) && (lOutputs.Count() > 0))
            {
                CInput oIn = lInputs.Find(element => element.sName == lInputs[0].sCalValue);
                if (oIn != null)
                {
                    lOutputs[0].sCalValue = oIn.sValue;
                }
            }
            return false;
        }
       

        private bool CalculateConstants()
        {
            foreach (COutput oOut in lOutputs)
            {
                if (oOut.sValue.ToLower().IndexOf("input>") == 0)
                {
                    string[] arrOut = oOut.sValue.Split('>');
                    if (arrOut.Count() == 2)
                    {
                        CInput oIn = lInputs.Find(element => element.sName == arrOut[1]);
                        if (oIn != null)
                            oOut.sCalValue = oIn.sCalValue;
                    }
                }
                else
                {
                    oOut.sCalValue = oOut.sValue;
                }                
            } 
            return false;
        }
                    

        private bool InputsEmpty()
        {
            bool bRet = false;
            foreach (CInput oIn in lInputs)
            {
                if (oIn.sCalValue == "")
                {
                    bRet = true;
                    break;
                }
            }
            return bRet;
        }

        private void DoCalculate()
        {
            try
            {
                // An If step must have 3 inputs ( A == B)
                // A and B and inputs, the == is the operator
                string sOperator = "", sA = "", sB = "";
                if (lInputs.Count < 2)
                {
                    sErrorCode = "2";
                    sErrorMessage = "'If' step must have 2 or 3 Inputs";
                }
                else
                {
                    sA = lInputs[0].sCalValue;
                    sOperator = lInputs[1].sValue;
                    // B os optional depending upon the sOperator
                    if (lInputs.Count >= 3)
                        sB = lInputs[2].sCalValue;

                    switch (sOperator.ToLower())
                    {
                        case "+":
                        case "&":
                            if (lOutputs.Count() > 0)
                                lOutputs[0].sCalValue = sA + sB;
                            break;
                        case "x":
                        case "*":
                            if (lOutputs.Count() > 0)
                            {
                                int n;
                                bool isNumeric1 = int.TryParse(sA, out n);
                                bool isNumeric2 = int.TryParse(sB, out n);
                                if ( isNumeric1 && isNumeric2)
                                    lOutputs[0].sCalValue = (Convert.ToInt64(sA) * Convert.ToInt64(sB)).ToString();
                            }
                            break;
                        case "!":
                            if (lOutputs.Count() > 0)
                            {
                                int n;
                                bool isNumeric1 = int.TryParse(sA, out n);                                
                                if (sA == "0")
                                    lOutputs[0].sCalValue = "1";
                                else
                                    lOutputs[0].sCalValue = "0";
                            }
                            break;
                    }
                    bCalculated = true;
                }
            }
            catch (Exception ex)
            {

            }
        }

        private void CalculateForList()
        {
            if (m_bFirstTimeInFor)
            {
                m_bFirstTimeInFor = false;
                m_FileSequence.sForStart = sId;
                m_iLoopCount = 0;
                try
                {
                    ForList.Clear();
                    StreamReader oStreamReader = new StreamReader(lInputs[0].sValue);
                    string sLine;
                    while ((sLine = oStreamReader.ReadLine()) != null)
                    {
                        if (sLine.Length>1)
                            ForList.Add(sLine);
                    }
                }
                catch (Exception oEx)
                {

                }
            }
            if (m_iLoopCount < ForList.Count)
            {
                string[] arrLine = ForList[m_iLoopCount++].Split('\t');
                for (int i = 0; i < lOutputs.Count(); i++)
                {
                    if (i < arrLine.Length)
                        lOutputs[i].sCalValue = arrLine[i];
                }
            }
            bCalculated = true;
        }

        public string CreateInput()
        {
            string sRet = "";
            switch (sType)
            {
                case "QueryDef":
                case "AlisWebService":
                    sRet = CreateInputQueryDef();
                    break;
                case "QueryDefUpdate":
                case "UpdateQueryDef":
                case "UpdateAlisWebService":
                    sRet = CreateInputUpdateQueryDef();
                    break;
            }
            return sRet;
        }

        private string CreateInputQueryDef()
        {
            string sRet = "";

            string sUserName = oIniFile.IniReadValue("QDHeader", "UserName");
            string sToken = oIniFile.IniReadValue("QDHeader", "Token");
            string sPassword = oIniFile.IniReadValue("QDHeader", "Password");
            string sLanguageId = oIniFile.IniReadValue("QDHeader", "LanguageId");
            string sCompanyId = oIniFile.IniReadValue("QDHeader", "CompanyId");


            sRet = "<Root><XMLHeader><MethodName>QueryDef</MethodName><UserName>$UserName$</UserName>$Password$<LanguageId>$LanguageId$</LanguageId><CompanyId>$CompanyId$</CompanyId></XMLHeader><XMLBody><Queries><Query Name=\"";
            sRet = sRet.Replace("$UserName$", sUserName);
            if (sPassword == "")
                sRet = sRet.Replace("$Token$", "<Token>" + sToken + "</Token>");
            else
                sRet = sRet.Replace("$Password$", "<Password>" + sPassword + "</Password>");
            sRet = sRet.Replace("$LanguageId$", sLanguageId);
            sRet = sRet.Replace("$CompanyId$", sCompanyId);
            sRet += sQueryName + "\"";
            if (sMode == "Debug")
                sRet += " Mode=\"1\" ";
            else if (sMode == "Schema")
                sRet += " Mode=\"2\" ";
            sRet += "><Param>\r\n";
            foreach (CInput oParam in lInputs)
            {
                sRet += "<" + oParam.sName + ">" + oParam.sCalValue + "</" + oParam.sName + ">\r\n";
            }

            sRet += "</Param></Query></Queries></XMLBody></Root>";
            return sRet;
        }

        private string CreateInputUpdateQueryDef()
        {
            string sUserName = oIniFile.IniReadValue("QDHeader", "UserName");
            string sToken = oIniFile.IniReadValue("QDHeader", "Token");
            string sPassword = oIniFile.IniReadValue("QDHeader", "Password");
            string sLanguageId = oIniFile.IniReadValue("QDHeader", "LanguageId");
            string sCompanyId = oIniFile.IniReadValue("QDHeader", "CompanyId");


            string sRet =  "<?xml version=\"1.0\" encoding=\"UTF8\"?><Root><XMLHeader><MethodName>Update</MethodName><UserName>$UserName$</UserName><Password>$Password$</Password><LanguageId>$LanguageId$</LanguageId><CompanyId>$CompanyId$</CompanyId></XMLHeader><XMLBody><Updates><Update $Mode$ Name=\"";
            sRet += sQueryName + "\">";

            

            foreach (CInput oIn in lInputs)
            {
                if ((oIn.sCalValue == "") || (oIn.sCalValue == null) )
                    oIn.sCalValue = oIn.sValue;
                if (oIn.sName.Substring(0,1) == "@")
                    sRet += oIn.sCalValue + "\r\n";
                else
                    sRet += "<" + oIn.sName + ">" + oIn.sCalValue + "</" + oIn.sName + ">\r\n";
            }

            sRet += "</Update></Updates></XMLBody></Root>";

            sRet = sRet.Replace("$UserName$", sUserName);
            sRet = sRet.Replace("$Token$", sToken);
            sRet = sRet.Replace("$Password$", sPassword);
            sRet = sRet.Replace("$LanguageId$", sLanguageId);
            sRet = sRet.Replace("$CompanyId$", sCompanyId);
            if (sMode == "None")
                sRet = sRet.Replace("$Mode$", "");
            else
                sRet = sRet.Replace("$Mode$", "Mode=\"" + sMode + "\"");

            return sRet;
        }

        private bool CalculateQueryDefProcess(string sInFilename, string sOutFilename, ref string sDebug)
        {
            bool bFinish = false;

            FileSequence oSequence = new FileSequence(sQueryName,m_connection);
            if (oSequence.oSteps.Count > 0)
            {

                // Before we start we need to pass any inputs to the first 
                // step 
                CStep oFirstStep = oSequence.oSteps[0];
                foreach (CInput oIn in lInputs)
                {
                    CInput oFirstStepIn = oFirstStep.lInputs.Find(element => element.sName == oIn.sName);
                    if (oFirstStepIn != null)
                    {
                        oFirstStepIn.sValue = oIn.sCalValue;
                        oFirstStepIn.sCalValue = oIn.sCalValue;
                    }
                }

                foreach (CStep oSt in oSequence.oSteps)
                {
                    foreach (CInput oIn in oSt.lInputs)
                    {
                        if (oIn.sValue == "?")
                        {
                            CInput oIn2 = lInputs.Find(element => element.sName == oIn.sName);
                            if (oIn2 != null)
                                oIn.sCalValue = oIn2.sValue;
                        }
                    }
                }

                sDebug = oSequence.Calculate();

                // now set any of the outputs from this step to the matching 
                // outputs from the last step in the process we just ran
                CStep oLastStep = oSequence.oSteps[oSequence.oSteps.Count - 1];
                foreach (COutput oOut in lOutputs)
                {
                    COutput oLastStepOut = oLastStep.lOutputs.Find(element => element.sName == oOut.sName);
                    if (oLastStepOut != null)
                    {
                        oOut.sCalValue = oLastStepOut.sCalValue;
                    }
                }
            }
            return bFinish;
        }

        private string CallFunction(string sName)
        {
            string sRet = "";
            String sName2 = sName.Replace("=", ""); sName = sName.Replace("(", ""); sName = sName.Replace(")", "");
            switch (sName2.ToUpper())
            {
                case "GETUNIQUETIN":
                    sRet = GetUniqueTIN();
                    break;
                default :
                    sRet = sName;
                    break;
            }
            return sRet;

        }

        private string GetUniqueTIN()
        {
            string sRet = DateTime.Now.ToString( "3ddHHmmss");
            return sRet;
        }
        
        public void CalculateSave(string sInFilename, string sOutFilename)
        {
            m_FileSequence.sLastError = "";
            // First check all the inputs have been calculated 
            foreach (CInput oIn in lInputs)
            {
                if (oIn != null)
                {
                    if (oIn.sValue == "?")
                    {
                        //To Do 
                        //Write Input box
                    }

                    string[] aIn = oIn.sValue.Split('>');
                    if (aIn.Length == 2)
                    {
                        string sStep = aIn[0]; string sInput = aIn[1];
                        CStep oSt = m_FileSequence.oSteps.Find(element => element.sName == sStep);
                        if (oSt != null)
                        {
                            if (!oSt.bCalculated)
                            {
                                oSt.Calculate("","");
                            }
                            COutput oOut = oSt.lOutputs.Find(element => element.sName == sInput);
                            if (oOut != null)
                                oIn.sCalValue = oOut.sCalValue;
                        }
                        else
                        {
                            m_FileSequence.sLastError += "Cant find (" + sStep + ") in (" + oIn.sName + ")\r\n";
                        }
                    }
                }
            }

            // Now do the actual calculation
            switch (sType)
            {
                case "Constants":
                    foreach (COutput oOut in lOutputs)
                    {
                        oOut.sCalValue = oOut.sValue;
                    }
                    bCalculated = true;
                    break;
                case "QueryDef":
                    CalculateQueryDef(sInFilename, sOutFilename);
                    break;

                case "AlisWebService":
                    CalculateAlisWebService(sInFilename, sOutFilename);
                    break;

                case "UpdateAlisWebService":
                    CalculateAlisWebService(sInFilename, sOutFilename);
                    break;

                case "UpdateQueryDef":
                    CalculateUpdateQueryDef(sInFilename, sOutFilename);
                    break;
            }
        }
    }

    public class FileSequence
    {
        public string         sLastError;
        public bool           bIfElseFlag = false;
        public bool           bIsDirty;
        public int            m_RunNum;
        public int            m_iId;
        public int            iCurrentStep;
        public string         sForStart;
        public int            iForCount;
        private DateTime      dStart;
        public string         sStreamLine = "";
        public string         sName;
        public List<CStep>    oSteps = new List<CStep>();
        public delegate void ErrorRaised(object sender, string sError);
        public event ErrorRaised Error;

        private DbConnection m_connection;
        private string m_sStartFile;

        public FileSequence()
        {
            dStart = DateTime.Now;
        }

        public FileSequence(DbConnection oConnection)
        {
            m_connection = oConnection;
            dStart = DateTime.Now;
        }

        private DbConnection GetConntion()
        {
            return m_connection;
        }

        public FileSequence(string sProcessName, DbConnection oConnection)
        {
            m_connection = oConnection;
            dStart = DateTime.Now;
            try
            {
                string sSql = "select * from t_api_qd_process where name ='" + sProcessName + "'";

                DbCommand command = GetConntion().CreateCommand();
                command.CommandText = sSql;
                command.CommandType = CommandType.Text;
                DbDataReader oDataReader = command.ExecuteReader();

                if (oDataReader.Read())
                {
                    if (oDataReader["ID"].ToString().Length > 0)
                    {
                        m_iId = Convert.ToInt16(oDataReader["ID"].ToString());
                        Load();
                    }
                }
                oDataReader.Close();
                oDataReader.Dispose();
            }
            catch (Exception ex)
            {
                if (Error != null)
                    Error(this, ex.Message);
            }
        }

        public string GetProcessName()
        {
            if (bIsDirty)
                return sName + "*";
            else
                return sName;
        }

        public string GetTime()
        {
            return DateTime.Now.Subtract(dStart).ToString();
        }

        public CStep FindStep( string sName)
        {
            CStep oStep = oSteps.Find(element => element.sName == sName);
            return oStep;
        }

        public string UnqueName(string sName)
        {
            int i = 1; string sTempName = sName;
            CStep oTemp = FindStep(sName);
            while (oTemp != null)
            {
                sTempName = sName + i++.ToString();
                oTemp = FindStep(sTempName);
            }
            return sTempName;
        }

        public override string ToString()
        {
            string sRet = "FileSequence: Steps(";
            sRet += oSteps.Count() + ") - " + DateTime.Now.Subtract(dStart).ToString() + "\r\n";
            foreach (CStep oStep in oSteps)
                sRet += oStep.ToString();
            return sRet;
        }

        public string sStartFile
        {
            get
            {
                return m_sStartFile;
            }
            set
            {
                CStep oNewStep = new CStep();
                m_sStartFile = value;
            }
        }

        private void AddParams(CStep oStep)
        {
            String sSql = "select * from T_API_QD_PROCESS_STEP_PARAMS where process_id=" + oStep.sProcessId + " and STEP_ID=" + oStep.sId;
            try
            {
                DbCommand command = GetConntion().CreateCommand();
                command.CommandText = sSql;
                command.CommandType = CommandType.Text;
                DbDataReader oDataReader = command.ExecuteReader();

                while (oDataReader.Read())
                {
                    string sInName = oDataReader["NAME"].ToString();
                    string sInValue = oDataReader["PARAMS_VALUE"].ToString();
                    string sID = oDataReader["ID"].ToString();
                    switch (oDataReader["PARAMS_TYPE"].ToString())
                    {
                        case "I":
                            if (sInName != null)
                            {
                                CInput oIn = new CInput(sInName, sInValue, sID, oStep);
                                oStep.lInputs.Add(oIn);
                            }

                            break;
                        case "O":
                            if (sInName != null)
                            {
                                COutput oOut = new COutput(sInName, sInValue, sID, oStep);
                                oStep.lOutputs.Add(oOut);
                            }
                            break;
                        case "D":
                            if (sInName != null)
                            {
                                CDisplay oDis = new CDisplay(sInName, sInValue, sID, oStep);
                                oStep.lDisplay.Add(oDis);
                            }
                            break;

                    }

                }
                oDataReader.Close();
                oDataReader.Dispose();
                command.Dispose();

            }
            catch (Exception ex)
            {
                if (Error != null)
                    Error(this, ex.Message + " (" + sSql + ")"); 
            }
        }

        private bool ToRunStep(CStep oStep)
        {
            bool bRet = true;

            if (bIfElseFlag != false)
            {
                if ((oStep.sType != "IF") && (oStep.sType != "ELSE") && (oStep.sType != "END IF"))
                    bRet = false;
            }
            return bRet;
        }

        public string Calculate()
        {
            string sDebug = "<UL>";
            bool bFinished = false;
            foreach (CStep oStep in oSteps)
            {
                if (ToRunStep(oStep))
                {
                    bFinished = oStep.Calculate("", "");
                    sDebug += "<LI>" + oStep.sId + " , " + oStep.sName + " , " + oStep.sType + " , " + oStep.dtStart.ToString("yyyy/MM/dd HH:mm:ss") + " , " + oStep.dtEnd.ToString("yyyy/MM/dd HH:mm:ss") + "\r\n";

                    sDebug += "<UL>";
                    foreach (CInput oIn in oStep.lInputs)
                        sDebug += "<LI>I(" + oIn.sName + ")=" + oIn.sCalValue;
                    sDebug += "</UL>";
                    sDebug += "<UL>";

                    foreach (COutput oOut in oStep.lOutputs)
                        sDebug += "<LI>O(" + oOut.sName + ")=" + oOut.sCalValue;
                    sDebug += "</UL>";
                }
                if (bFinished)
                    break;

            }
            return sDebug + "</UL>";
        }

        public void Load()
        {
            String sSql = "select t_api_qd_process.name as process, t_api_qd_process_step.ID,t_api_qd_process_step.PROCESS_ID,";
            sSql += "          t_api_qd_process_step.NAME,t_api_qd_process_step.QUERY_NAME,t_api_qd_process_step.STEP_MODE, ";
            sSql += "          t_api_qd_process_step.TYPE sType ";
            sSql += "from t_api_qd_process ";
            sSql += "left outer join t_api_qd_process_step on  t_api_qd_process.id =  t_api_qd_process_step.process_id ";
            sSql += "where t_api_qd_process.id = " + m_iId.ToString() + " ";
            sSql += "order by t_api_qd_process_step.ID";

            try
            {
                DbCommand command = GetConntion().CreateCommand();
                command.CommandText = sSql;
                command.CommandType = CommandType.Text;
                DbDataReader oDataReader = command.ExecuteReader();
                
                while (oDataReader.Read())
                {
                    if (oDataReader["ID"].ToString().Length > 0)
                    {
                        CStep oStep = new CStep(oDataReader, m_connection, this);
                        AddParams(oStep);
                        oSteps.Add(oStep);                            
                    }
                }
                oDataReader.Close();
                oDataReader.Dispose();
                command.Dispose();
            }
            catch (Exception ex)
            {
                if (Error != null)
                    Error(this, ex.Message + " (" + sSql + ")");
            }
        }
    }    
}
